Implement flat_map operator#374
Conversation
| { | ||
| copy_count_tracker verifier{}; | ||
| auto obs = rpp::source::just<TestType>(std::move(verifier)) | ||
| | rpp::ops::flat_map([](copy_count_tracker&& verifier) { return rpp::source::just<TestType>(std::move(verifier)); }); |
There was a problem hiding this comment.
@victimsnino do you know why sources don't move objects through operators? Preventing me from taking verifier as an rvalue ref here
There was a problem hiding this comment.
Because it would be moved IF possible, but no guarantees. If it would be only pure rvalue, then it means second repeated subscribe would see nothing :)
There was a problem hiding this comment.
I see, I added some cases for copies then
There was a problem hiding this comment.
if you would use create with std::move inside, then it would be moved inside lambda
| TEST_RPP([&]() | ||
| { | ||
| rpp::source::create<int>([](const auto& obs){ obs.on_next(1); }) | ||
| | rpp::operators::flat_map([](int v) { return rpp::source::just(v * 2); }) |
There was a problem hiding this comment.
Could you use “create” there instead of just to measure there only “flat_map”, not “just” ? :)
Codecov Report
@@ Coverage Diff @@
## v2 #374 +/- ##
==========================================
+ Coverage 99.12% 99.13% +0.01%
==========================================
Files 37 38 +1
Lines 802 812 +10
==========================================
+ Hits 795 805 +10
Misses 7 7
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
| RPP_NO_UNIQUE_ADDRESS Fn m_fn; | ||
|
|
||
| template<rpp::constraint::observable TObservable> | ||
| requires std::invocable<Fn, rpp::utils::extract_observable_type_t<TObservable>> |
There was a problem hiding this comment.
There is also invocation result must be observable
There was a problem hiding this comment.
It is already required here isn't it enough?
There was a problem hiding this comment.
No, check this comment
https://github.com/victimsnino/ReactivePlusPlus/pull/374/files#r1225415597
| auto operator()(TObservable&& observable) && | ||
| { | ||
| return std::forward<TObservable>(observable) | ||
| | rpp::ops::map(std::forward<Fn>(m_fn)) |
| auto map(Fn&& callable); | ||
|
|
||
| template<typename Fn> | ||
| requires rpp::constraint::observable<std::invoke_result_t<Fn, utils::convertible_to_any>> |
There was a problem hiding this comment.
Add check over !utils::is_not_template_callable as in map. It needed when passed function is purely template. For example [](auto v) {return rpp::source::just(v); } wouldn't satisfy your requirement
There was a problem hiding this comment.
done, added a test too
|
|
||
| template<rpp::constraint::observable TObservable> | ||
| requires std::invocable<Fn, rpp::utils::extract_observable_type_t<TObservable>> | ||
| template<rpp::constraint::observable TObservable, typename ValueType = rpp::utils::extract_observable_type_t<TObservable>> |
There was a problem hiding this comment.
I see your attempt with ValueType to avoid duplicates, but it would affect final binaries due to it would be compiled-in as template function with 2 params instead of one =C it is better to create special concept instead
| CHECK(mock.get_on_error_count() == 1); | ||
| } | ||
| } | ||
| SECTION("subscribe using flat_map with templated lambda") |
There was a problem hiding this comment.
i think, you can just place it in a748a6f#diff-4ad61bca345fc2ef117d5617e164dca71340d801c636340f2c051a5bd4e6e9d2R37
| auto obs = rpp::source::create<copy_count_tracker>([verifier = std::move(verifier)](const auto& obs) { obs.on_next(verifier); }) | ||
| | rpp::ops::map([](copy_count_tracker verifier) { return std::move(verifier); }) // copy from source to map |
There was a problem hiding this comment.
try instead
auto obs = rpp::source::create<copy_count_tracker>([verifier = std::move(verifier)](const auto& obs) { obs.on_next(std::move(verifier)); })There was a problem hiding this comment.
Though I subscribe two times here, so verifier will be in an invalid state in second subscription as it was already moved no?
There was a problem hiding this comment.
I changed to capture by ref and pass by value
There was a problem hiding this comment.
Though I subscribe two times here, so verifier will be in an invalid state in second subscription as it was already moved no?
No, verifier is special class that is valid after move =)
| CHECK(mock.get_on_error_count() == 0); | ||
| } | ||
| } | ||
| SECTION("subscribe using flat_map with error in middle") |
There was a problem hiding this comment.
Could you also add test over never in middle? to check that it is actually map + merge, not map + concat =)
| } | ||
| } | ||
|
|
||
| TEST_CASE("flat_map copies/moves") |
There was a problem hiding this comment.
I think, you can remove this test_case due to you are trying to test map + test merge at the same time, it is pretty hard. It is better to have corresponding tests to map and merge. I'm going to add them later.
There was a problem hiding this comment.
yeah agree, done
| template<rpp::constraint::observable TObservable> | ||
| requires (std::invocable<Fn, rpp::utils::extract_observable_type_t<TObservable>> | ||
| && rpp::constraint::observable<std::invoke_result_t<Fn, rpp::utils::extract_observable_type_t<TObservable>>>) | ||
| auto operator()(TObservable&& observable) const & |
There was a problem hiding this comment.
Can you add test to cover this overloading? (it is enough to apply operator from variable in any test case)
|
Thanks for PR =) |
Should I also implement a variant taking a
ResultSelectorlike in rxcpp?